package com.maple.common.widget.step

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.graphics.RectF
import android.graphics.Region
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.core.content.withStyledAttributes
import com.maple.common.R
import com.maple.common.ext.dpToPx
import kotlin.math.tan


/**
 * Tip: 顶部三个多边形组成的进度
 *
 * Create by SeVen on 2024/11/15 9:21
 */
class StepPolygonView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    /**
     * Text paint
     */
    private val textPaint: Paint = Paint()

    /**
     * Polygon paint
     */
    private val polygonPaint: Paint = Paint()

    /**
     * Left region
     */
    private var leftRegion: Region? = null

    /**
     * Left region
     */
    private var centerRegion: Region? = null

    /**
     * right region
     */
    private var rightRegion: Region? = null


    /**
     * Angle角度 （为每一个凹凸部分的夹角，为底部小的部分，用于计算凹凸部分的宽度）
     */
    private var angleInDegrees: Double = 60.0

    /**
     * Item white spacing
     */
    private var itemWhiteSpacing = 0

    /**
     * Other white spacing
     */
    private var otherWhiteSpacing = 0

    /**
     * Unit width
     */
    private var unitWidth: Int = 0

    /**
     * W
     */
    private var w: Int = 0

    /**
     * H
     */
    private var h: Int = 0

    /**
     * 每一个凹凸出来部分的宽度
     */
    private var conW: Float = 0.0f

    /**
     * Step
     */
    private var step: Int = 1

    private var stepFinishColor = Color.BLUE

    private var stepCurrentColor: Int = Color.RED

    private var stepOtherColor: Int = Color.GRAY

    private var stepText: Array<String>? = null

    private var stepCurrentTextColor: Int = Color.WHITE

    private var stepCurrentTextSize: Float = 10f

    private var stepOtherTextColor: Int = Color.BLACK

    private var stepOtherTextSize: Float = 0f

    private var zoomSize: Float = 0f

    private var zoomStep = 1

    private var onPositionCallback: ((Int) -> Unit)? = null

    fun setOnPositionCallback(onPositionCallback: ((Int) -> Unit)?) {
        this.onPositionCallback = onPositionCallback
    }

    /**
     * Position
     */
    private var position = 0

    init {
        initAttrs(context, attrs)
        initData()
        initPaint()
    }

    private fun initData() {
        if (step < 1) {
            step = 1
        }
        if (step > 4) {
            step = 4
        }

        if (stepText == null || stepText!!.size != 3) {
            stepText = null
        }
    }


    private fun initAttrs(context: Context, attrs: AttributeSet?) {
        context.withStyledAttributes(attrs, R.styleable.StepPolygonView) {
            step = getInt(R.styleable.StepPolygonView_step_current, step)
            stepFinishColor =
                getColor(R.styleable.StepPolygonView_step_finish_color, stepFinishColor)
            stepCurrentColor =
                getColor(R.styleable.StepPolygonView_step_current_color, stepCurrentColor)
            stepOtherColor =
                getColor(R.styleable.StepPolygonView_step_other_color, stepOtherColor)
            val stepContent = getResourceId(R.styleable.StepPolygonView_step_text, 0)
            if (stepContent != 0) {
                stepText = context.resources.getStringArray(stepContent)
            }
            stepCurrentTextColor = getColor(
                R.styleable.StepPolygonView_step_current_textColor,
                stepCurrentTextColor
            )
            stepCurrentTextSize = getDimension(
                R.styleable.StepPolygonView_step_current_textSize,
                dpToPx(context, 12f)
            )
            stepOtherTextColor =
                getColor(
                    R.styleable.StepPolygonView_step_other_textColor,
                    stepOtherTextColor
                )
            stepOtherTextSize =
                getDimension(
                    R.styleable.StepPolygonView_step_other_textSize,
                    dpToPx(context, 12f)
                )
            angleInDegrees =
                getFloat(R.styleable.StepPolygonView_step_angleInDegrees, 60f).toDouble()

            itemWhiteSpacing = getDimension(
                R.styleable.StepPolygonView_step_itemWhiteSpacing, dpToPx(context, 4f)
            ).toInt()
            otherWhiteSpacing =
                getDimension(R.styleable.StepPolygonView_step_otherWhiteSpacing, 0f).toInt()
            zoomSize =
                getFloat(R.styleable.StepPolygonView_step_zoomSize, dpToPx(context, 1f))
        }
    }

    /**
     * Init left
     *
     */
    private fun initPaint() {
        polygonPaint.color = stepCurrentColor
        polygonPaint.isAntiAlias = true
        //Text画笔
        textPaint.color = Color.WHITE
        textPaint.textAlign = Paint.Align.CENTER
        textPaint.textSize = stepCurrentTextSize
    }


    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        drawLeft(canvas, zoomStep == 1)
        drawCenter(canvas, zoomStep == 2)
        drawRight(canvas, zoomStep == 3)
    }

    private fun drawLeft(canvas: Canvas, isZoom: Boolean = false) {
        if (step > 1) {
            polygonPaint.color = stepFinishColor
        } else {
            polygonPaint.color = stepCurrentColor
        }
        textPaint.color = stepCurrentTextColor
        textPaint.textSize = stepCurrentTextSize
        val moveX: Float = (otherWhiteSpacing / 2).toFloat()//左边点的位置
        val moveY = if (isZoom) {
            0f
        } else {
            zoomSize
        }
        val rightPointX = moveX + unitWidth
        //中间凸出来到原点的Y坐标
        val convexX = rightPointX + conW
        val pointHeight = h.toFloat() - moveY
        val convexPointHeight: Float = h / 2f

        val path = Path()
        path.moveTo(moveX, moveY)
        path.lineTo(rightPointX, moveY)
        path.lineTo(convexX, convexPointHeight)
        path.lineTo(rightPointX, pointHeight)
        path.lineTo(moveX, pointHeight)
        //绘制部分
        canvas.drawPath(path, polygonPaint)

        if (stepText != null && stepText?.size == 3) {
            drawText(stepText!![0], canvas, moveX, 0f, rightPointX, pointHeight)
        }

        leftRegion = getRegion(path)
    }

    /**
     *
     * Draw center
     *
     * @param canvas
     * @param isZoom  是否放大
     */
    private fun drawCenter(canvas: Canvas, isZoom: Boolean = false) {
        if (step == 1) {
            polygonPaint.color = stepOtherColor
            textPaint.color = stepOtherTextColor
            textPaint.textSize = stepOtherTextSize
        }
        if (step == 2) {
            polygonPaint.color = stepCurrentColor
            textPaint.color = stepCurrentTextColor
            textPaint.textSize = stepCurrentTextSize
        }
        if (step > 2) {
            polygonPaint.color = stepFinishColor
            textPaint.color = stepCurrentTextColor
            textPaint.textSize = stepCurrentTextSize
        }
        val moveX: Float = unitWidth.toFloat() + itemWhiteSpacing + otherWhiteSpacing / 2//左边点的位置
        val moveY = if (isZoom) {
            0f
        } else {
            zoomSize
        }
        val rightPointX: Float = moveX + unitWidth
        //中间凸出来到原点的Y坐标
        val convexX = rightPointX + conW
        //中间凹进去到原点的Y坐标
        val concaveX = moveX + conW
        //中间凸出来到原点的Y坐标
        val pointHeight = h.toFloat() - moveY
        val conPointHeight: Float = h / 2f

        val path = Path()
        path.moveTo(moveX, moveY)
        path.lineTo(rightPointX, moveY)
        path.lineTo(convexX, conPointHeight)
        path.lineTo(rightPointX, pointHeight)
        path.lineTo(moveX, pointHeight)
        path.lineTo(concaveX, conPointHeight)
        //绘制部分
        canvas.drawPath(path, polygonPaint)
        //绘制中间的文字
        if (stepText != null && stepText?.size == 3) {
            drawText(stepText!![1], canvas, moveX, 0f, rightPointX, pointHeight)
        }
        //计算B区域可点击部分

        centerRegion = getRegion(path)

    }

    private fun drawRight(canvas: Canvas, isZoom: Boolean = false) {
        if (step < 3) {
            polygonPaint.color = stepOtherColor
            textPaint.color = stepOtherTextColor
            textPaint.textSize = stepOtherTextSize
        }
        if (step == 3) {
            polygonPaint.color = stepCurrentColor
            textPaint.color = stepCurrentTextColor
            textPaint.textSize = stepCurrentTextSize
        }
        if (step > 3) {
            polygonPaint.color = stepFinishColor
            textPaint.color = stepCurrentTextColor
            textPaint.textSize = stepCurrentTextSize
        }
        val moveX: Float =
            (unitWidth * 2).toFloat() + itemWhiteSpacing * 2 + otherWhiteSpacing / 2//左边点的位置
        val moveY = if (isZoom) {
            0f
        } else {
            zoomSize
        }
        val rightPointX = moveX + unitWidth
        //中间凹进去到原点的Y坐标
        val concaveX = moveX + conW
        //中间凸出来到原点的Y坐标
        val pointHeight = h.toFloat() - moveY
        val conPointHeight: Float = h / 2f

        val path = Path()
        path.moveTo(moveX, moveY)
        path.lineTo(rightPointX, moveY)
        path.lineTo(rightPointX, pointHeight)
        path.lineTo(moveX, pointHeight)
        path.lineTo(concaveX, conPointHeight)
        //绘制多变形部分
        canvas.drawPath(path, polygonPaint)
        //绘制中间的文字
        if (stepText != null && stepText?.size == 3) {
            drawText(stepText!![2], canvas, moveX, 0f, rightPointX, pointHeight)
        }


        rightRegion = getRegion(path)
    }


    /**
     * Get region
     *
     * @param path
     */
    private fun getRegion(path: Path): Region {
        val clickRegion = Region()
        val bounds = RectF()
        path.computeBounds(bounds, true)
        val region = Region(
            bounds.left.toInt(), bounds.top.toInt(), bounds.right.toInt(), bounds.bottom.toInt()
        )
        clickRegion.setPath(path, region)
        return clickRegion
    }

    private fun drawText(
        text: String,
        canvas: Canvas, left: Float, top: Float, right: Float, bottom: Float
    ) {
        val rect = RectF(left, top, right, bottom)
        //计算baseline
        val fontMetrics: Paint.FontMetrics = textPaint.getFontMetrics()
        val distance = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom
        val baseline: Float = rect.centerY() + distance
        canvas.drawText(text, rect.centerX(), baseline, textPaint)
    }

    /**
     * 设置当前步骤
     * Set step
     *
     * @param step
     */
    fun setStep(step: Int) {
        this.step = step
        invalidate()
    }

    /**
     * Set zoom step
     *
     * @param zoomStep
     */
    fun setZoomStep(zoomStep: Int) {
        this.zoomStep = zoomStep
        invalidate()
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        this.w = w
        this.h = h
        unitWidth = (w - otherWhiteSpacing - itemWhiteSpacing * 2) / 3
        //计算每一个凹凸部分的宽度
        val angleInRadians = Math.toRadians(angleInDegrees)
        conW = (h / 2) / tan(angleInRadians).toFloat()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        //计算每一个多边形的宽度和宽度，宽度为整体的1/3 - 中间间隔-内边距和外边距
        setMeasuredDimension(measuredWidth(), measuredHeight(heightMeasureSpec))
    }

    private fun getMeasureSpaceInfo(measureSpec: Int): Pair<Int, Int> {
        //测量模式，从xml获取
        val specMode = MeasureSpec.getMode(measureSpec)
        //测量大小，从xml获取
        val specSize = MeasureSpec.getSize(measureSpec)
        return Pair(specMode, specSize)
    }

    private fun measureSize(specMode: Int, specSize: Int, defaultSpecSize: Int): Int {
        return if (specMode == MeasureSpec.EXACTLY) specSize else {
            if (specMode == MeasureSpec.AT_MOST) {
                defaultSpecSize.coerceAtMost(specSize)
            } else defaultSpecSize
        }
    }

    //默认整个控件的宽度为当前屏幕的宽度-otherWhiteSpacing边距
    private fun measuredWidth(): Int {
        val width = (getWindowWidth(context))
        w = width
        return width
    }

    //高度自己去测量默认最小的高度为36dp
    private fun measuredHeight(heightMeasureSpec: Int): Int {
        val (specMode, specSize) = getMeasureSpaceInfo(heightMeasureSpec)
        val defaultSpecSize = dpToPx(context, 28f)
        val height = measureSize(specMode, specSize, defaultSpecSize.toInt())
        h = height
        return height
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when (event?.action) {
            MotionEvent.ACTION_UP -> {
                if (isInPolygon(event.x, event.y)) {
                    performClick();
                }
            }
        }
        return true
    }

    override fun performClick(): Boolean {
        super.performClick()
        //刷新draw 将图形放大
        onPositionCallback?.invoke(position)
        when (position) {
            0 -> {
                zoomStep = 1
                invalidate()
            }

            1 -> {
                zoomStep = 2
                invalidate()
            }

            2 -> {
                zoomStep = 3
                invalidate()
            }
        }
        return true
    }

    private fun isInPolygon(x: Float, y: Float): Boolean {
        if (leftRegion?.contains(x.toInt(), y.toInt()) == true) {
            position = 0
        }

        if (centerRegion?.contains(x.toInt(), y.toInt()) == true) {
            position = 1
        }

        if (rightRegion?.contains(x.toInt(), y.toInt()) == true) {
            position = 2
        }
        return true
    }

    // 屏幕宽度（像素）
    private fun getWindowWidth(context: Context): Int {
        val res = context.resources
        val metric = res.displayMetrics
        return metric.widthPixels
    }
}